/*
 *  pop3.c
 *
 *  Very simple POP3 email interface.  With SSL support.
 *
 * Copyright (c) 2006 Karlan Thomas Mitchell<karlanmitchell@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, is prohibited except by
 * Karlan Thomas Mitchell.
 *
 * THIS SOFTWARE IS PROVIDED BY KARLAN THOMAS MITCHELL AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */ 

#include "pop3.h"

int pop3_init(struct st_pop3 * pop3_data){
	return 0;
	}

int pop3_reset(struct st_pop3 * pop3_data){
	pop3_disconnect(pop3_data);
	return pop3_internal_connect(pop3_data);
	}


int pop3_del_email(struct st_pop3 * pop3_data, int email){
	char buffer[1024];
	snprintf(buffer, 1024, "DELE %d\x0D\x0A", email);
	psocket_write(&pop3_data->connection, buffer, strlen(buffer));
#if POP3_DEBUG
	printf("C %s", buffer);
#endif

	psocket_readline_r(&pop3_data->connection, buffer, 1024);
#if POP3_DEBUG
	printf("S %s\n", buffer);
#endif
	if(strncasecmp(buffer, "+OK", 3) != 0)
		return POP3ERROR_DEL;

	return 0;
	}

int pop3_load_email(struct st_pop3 * pop3_data, int email, char * email_buffer, size_t buf_len){
	email_buffer[0] = 0; 

	char buffer[1024];
	snprintf(buffer, 1024, "RETR %d\x0D\x0A", email);
	psocket_write(&pop3_data->connection, buffer, strlen(buffer));
#if POP3_DEBUG
	printf("C %s", buffer);
#endif

	psocket_readline_r(&pop3_data->connection, buffer, 1024);
#if POP3_DEBUG
	printf("S %s\n", buffer);
#endif
	if(strncasecmp(buffer, "+OK", 3) != 0)
		return POP3ERROR_RETR;

	
	while(1){
		psocket_readline_r(&pop3_data->connection, buffer, 1024);
#if POP3_DEBUG
		printf("S %s\n", buffer);
#endif

		if(strcmp(buffer, ".") == 0)
			break;
	 	strlcat(email_buffer, buffer, buf_len);
	 	strlcat(email_buffer, "\n", buf_len);
	}


	return 0;
	}






int pop3_stat(struct st_pop3 * pop3_data){
	char buffer[1024];

	snprintf(buffer, 1024, "STAT\x0D\x0A");
	psocket_write(&pop3_data->connection, buffer, strlen(buffer));
#if POP3_DEBUG
	printf("C %s", buffer);
#endif

	psocket_readline_r(&pop3_data->connection, buffer, 1024);
#if POP3_DEBUG
	printf("S %s\n", buffer);
#endif
	/*Please note the extra space is essential in the comparision!*/
	if(strncasecmp(buffer, "+OK ", 4) != 0)
		return POP3ERROR_STAT;

	char *  messages_pntr = &*(buffer + 4);
	pop3_data->messages = atoi(messages_pntr);
	return pop3_data->messages;
	}





/*Called internally ONLY!  uses data filled in by pop3_connect*/
int pop3_internal_connect(struct st_pop3 * pop3_data){
	char buffer[1024];


	psocket_connect(&pop3_data->connection, pop3_data->server, pop3_data->port);


	psocket_readline_r(&pop3_data->connection, buffer, 1024);
#if POP3_DEBUG
	printf("S %s\n", buffer);
#endif
	if(strncasecmp(buffer, "+OK", 3) != 0)
		return POP3ERROR_CONNECTION;


	snprintf(buffer, 1024, "USER %s\x0D\x0A", pop3_data->user);
	psocket_write(&pop3_data->connection, buffer, strlen(buffer));
#if POP3_DEBUG
	printf("C %s", buffer);
#endif


	psocket_readline_r(&pop3_data->connection, buffer, 1024);
#if POP3_DEBUG
	printf("S %s\n", buffer);
#endif
	if(strncasecmp(buffer, "+OK", 3) != 0)
		return POP3ERROR_AUTH;


	snprintf(buffer, 1024, "PASS %s\x0D\x0A", pop3_data->password);
	psocket_write(&pop3_data->connection, buffer, strlen(buffer));
#if POP3_DEBUG
	printf("C %s", buffer);
#endif


	psocket_readline_r(&pop3_data->connection, buffer, 1024);
#if POP3_DEBUG
	printf("S %s\n", buffer);
#endif
	if(strncasecmp(buffer, "+OK", 3) != 0)
		return POP3ERROR_AUTH;
	


	return 0;
	}

int pop3_connect(struct st_pop3 * pop3_data, char * pop3server, char * user, char * password, int ssl){
	char server[1024];
	strcpy(server, pop3server);

	pop3_data->ssl  = ssl;	
	pop3_data->port = 110;
	strncpy(pop3_data->user, user, 1024);	
	strncpy(pop3_data->password, password, 1024);	

	if(ssl)
		pop3_data->connection.io_method = IO_OPENSSL;
	else
		pop3_data->connection.io_method = IO_BSD;

	char * pntr;
	char * port_pntr;

         port_pntr = strchr(server, ':');
   	 if(port_pntr != NULL){
		*(port_pntr) = 0;
   		*(port_pntr++);
   		pop3_data->port = atoi( port_pntr );
		}
	
	
	struct hostent * host_ent;
	host_ent = (struct hostent *)gethostbyname(server);

	
	if(host_ent != NULL)
		snprintf(pop3_data->server, 1024, "%s", inet_ntoa(  *( struct in_addr*)( host_ent -> h_addr) )  );
	else 
		strncpy(pop3_data->server, server, 1024);

	
	return pop3_internal_connect(pop3_data);
	}



int pop3_disconnect(struct st_pop3 * pop3_data){
	char buffer[1024];
	snprintf(buffer, 1024, "QUIT\x0D\x0A", pop3_data->password);
	psocket_write(&pop3_data->connection, buffer, strlen(buffer));
#if POP3_DEBUG
	printf("C %s", buffer);
#endif
	psocket_readline_r(&pop3_data->connection, buffer, 1024);
#if POP3_DEBUG
	printf("S %s\n", buffer);
#endif



	psocket_shutdown(&pop3_data->connection);
	return 0;
	}

int pop3_free(struct st_pop3 * pop3_data){
	return 0;
	}

